#pragma once

namespace AVUI {

/// <summary>Specifies the culture, case, and sort rules to be used by certain overloads of the <see cref="M:System.String.Compare(System.String,System.String)" /> and <see cref="M:System.String.Equals(System.Object)" /> methods.</summary>
class StringComparison
{
public:
    enum Enum
    {
    /// <summary>Compare strings using culture-sensitive sort rules and the current culture.</summary>
    CurrentCulture = 0,
    /// <summary>Compare strings using culture-sensitive sort rules, the current culture, and ignoring the case of the strings being compared.</summary>
    CurrentCultureIgnoreCase = 1,
    /// <summary>Compare strings using culture-sensitive sort rules and the invariant culture.</summary>
    InvariantCulture = 2,
    /// <summary>Compare strings using culture-sensitive sort rules, the invariant culture, and ignoring the case of the strings being compared.</summary>
    InvariantCultureIgnoreCase = 3,
    /// <summary>Compare strings using ordinal sort rules.</summary>
    Ordinal = 4,
    /// <summary>Compare strings using ordinal sort rules and ignoring the case of the strings being compared.</summary>
    OrdinalIgnoreCase = 5
    };
};


class String : public Object
{
public:
    DECLARE_ELEMENT(String, Object);

    String() : m_wzData(NULL), m_cch(0) { };

    String(const char* szString, int cch = -1);
    String(const WCHAR* wzString, int cch = -1);
    String(const WCHAR* pwch, int startIndex, int cch);
    String(TArrayPtr<WCHAR> rgWch, int startIndex, int cch);
    String(const String& strOther);

    bool operator==(const String& rhs) const;
    bool operator!=(const String& rhs) const;
    String& operator=(const String& rhs);

    ~String();


    void CopyTo(int sourceIndex, TArrayPtr<WCHAR> destination, int destinationIndex, int count);

    TRefCountedPtr<String> Append(const WCHAR* pwz);
    static TRefCountedPtr<String> Concat(TRefCountedPtr<String> str0, TRefCountedPtr<String> str1);
    static int Compare(String* pStrA, String* pStrB, StringComparison::Enum comparisonType);

    bool Equals(const Object* pOther) const;
    bool Equals(const WCHAR* pwchOther, bool isInsensitive = false, int cchOther = -1) const;
    bool Equals(const char* pchOther, bool isInsensitive = false, int cchOther = -1) const;
    bool BeginsWith(const WCHAR* pwch, int cch) const;
    bool EndsWith(const WCHAR* pwch, int cch) const;

    void ConvertToAnsi(char* pszBuffer, unsigned int cchMaxBuffer);
    bool IsEqualToAnsi(char* pszAnsiStr);
    TRefCountedPtr<String> Insert(int startIndex, String* pValue);
    TRefCountedPtr<String> Remove(int startIndex, int count);
    TRefCountedPtr<String> Replace(WCHAR oldChar, WCHAR newChar);
 

    void Trim();
    TRefCountedPtr<String> Trim(const WCHAR* rgTrimChars, int cTrimChars);
    void InsertAt(int idx, WCHAR wch);
    void DeleteAt(int idx);

    int IndexOf(WCHAR wch, int startIndex = 0) const;
    int LastIndexOf(WCHAR wch) const;

    const WCHAR* get_Ptr() const { return m_wzData; }
    int get_Cch() const { return m_cch; }
    WCHAR operator [] (int i) const { if(i >= m_cch) LibraryCriticalError(); return m_wzData[i]; }
    static bool IsWhiteSpace(WCHAR wch) { if(wch != L' ' && (wch < L'\t' || wch > L'\r') && wch != 0x00A0 && wch != 0x0085) return false; return true; }
    static bool IsNullOrEmpty(String* pString) { return pString == NULL || pString->m_cch == 0; }

    TRefCountedPtr<String> Substring(int index, int cch) const;
    TRefCountedPtr<String> Substring(int index) const;
    TRefCountedPtr<String> ToLower() const;
    bool Contains(WCHAR wch) const { return IndexOf(wch) != -1; }
    static String* get_Empty() { static String emptyString(""); return &emptyString; }

private:

    WCHAR* m_wzData;
    int m_cch;
};

// Used to wrap const string buffers into an appropriate container.
extern TRefCountedPtr<String> _S(const char* szText);
extern TRefCountedPtr<String> _S(const WCHAR* wzText);


class StringTypeConverter : public TypeConverter
{
public:
    virtual bool CanConvertFrom(Object* pContext, const Type& type) const;
    virtual ObjectPtr ConvertFrom(Object* pContext, Object* pObjectFrom) const;
    virtual bool CanConvertTo(Object* pContext, const Type& type) const { return false; };
    virtual ObjectPtr ConvertTo(Object* pContext, Object* pObjectFrom, const Type& type) const { LibraryCriticalError(); return NULL; }
};


typedef TRefCountedPtr<String> StringPtr;

};


